//
//  SpeedCoachComms.m
//  SpeedCoach Importer
//
//  Created by Roelant Ossewaarde on 4/8/11.
//  Copyright 2011 SUNY Buffalo. All rights reserved.
//

#import "SpeedCoachComms.h"
#import "serialcomms.h"


@implementation SpeedCoachComms


-(id) init {
	if (self = [super init]) {
		filedescriptor = -1;
		appDelegate = (SpeedCoach_Importer_AppDelegate *)[NSApp delegate];

	}
	return self;
}

-(int) initializeComms {
	
	// initialize the fds set (for use by select) 

	[appDelegate log:@"AppplicationController:performImportFromSpeedCoachXL:calling open()" severity:0];
    filedescriptor = open("/dev/tty.KeySerial1", O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (filedescriptor == -1)
	{
		NSString *logMessage = [NSString stringWithFormat:@"AppplicationController:performImportFromSpeedCoachXL:Error opening serial port %s - %s(%d).\n",
								"/dev/tty", strerror(errno), errno];
		[appDelegate log:logMessage severity:2];
		return -1;
    }
	[appDelegate log:@"AppplicationController:performImportFromSpeedCoachXL:Serial port opened OK" severity:0];
	//	NSLog(@"ISSET: %d", FD_ISSET(fileDescriptor)
	initport(filedescriptor);
	return filedescriptor;
}

-(void) close {
	// first few filedescriptors are STDIN etc. - never close those. 
	if (filedescriptor > 4) {
		close(filedescriptor);	
	}
}

void initport(int fd) {
	struct termios options;
	// Get the current options for the port...
	tcgetattr(fd, &options);
	// Set the baud rates to 19200...
	cfsetispeed(&options, B2400);
	cfsetospeed(&options, B2400);
	// Enable the receiver and set local mode...
	options.c_cflag |= (CLOCAL | CREAD);
	
	options.c_cflag &= ~PARENB;
	options.c_cflag &= ~CSTOPB;
	options.c_cflag &= ~CSIZE;
	options.c_cflag |= CS8;
	
	// Set the new options for the port...
	tcsetattr(fd, TCSANOW, &options);
}

/* will return YES if there is data available; timeout is set in this function. Won't read or reset fds */
-(BOOL) isDataAvailable {
	struct timeval       timeout;
	timeout.tv_sec = 2	;
	timeout.tv_usec = 0;
	FD_ZERO(&fds);
	FD_SET(filedescriptor, &fds);

	int result = select(filedescriptor + 1, &fds, NULL, NULL, &timeout);
	if (result > 0) {
		if (FD_ISSET(filedescriptor, &fds)) return YES;
	}
	return NO;
}

/* flushes comms by reading any data that is currently in the buffer */
-(void) flushComms {
	char buf[1024];
	[appDelegate log:@"Flushing COM." severity:0];

	while ([self isDataAvailable]) {
		read(filedescriptor, &buf, 1024);
	}
	return;
}
	
-(BOOL) pingSpeedCoach {
	char buf[1024];
	char ping_cmd[1024];
	strcpy(ping_cmd, "+");
	BOOL echoed_back = NO;
	int i=0;
	[self flushComms];
	do {
		[appDelegate log:@"Checking to see if the SpeedCoach is available for communication." severity:0];
		int	result = write(filedescriptor, ping_cmd, strlen(ping_cmd));
		if (result == -1) {
			NSLog(@"writing: error %i, %s\n", errno, strerror(errno));
			[appDelegate log:@"Error writing to the COM-port (error 3)." severity:2];
			return NO;
		}
		sleep(1);
		if ([self isDataAvailable]) {
			result = read(filedescriptor, &buf, 1024);
			if (buf[0] == 0x2b && buf[1] == 0x0d && buf[2] == 0x0a && buf[3] == 0x3e && buf[4] == 0x20) {
				echoed_back = YES;
			}
		}
			
		i++;
	} while (i < 5 && echoed_back == NO);
	return echoed_back;

}

-(NSData *) readEprom:(int)eprom {
	char buf[1024];
	int result;
	fd_set fds;
	struct timeval       timeout;
	
	int total_bytes_read = 0;
	int threshold = 0;
	int exit_condition = 0;
	int i;
	NSMutableData *buffer = [[NSMutableData alloc] init];
	FILE *f;
	char filename[1023];
	
	// send a 'd'-command to read first eprom; 'm' to read second eprom
	if (eprom == 0) {
		strcpy(buf, "d");
		[appDelegate log:@"Downloading data from eprom 1" severity:0];
	} else {
		strcpy(buf, "m");
		[appDelegate log:@"Downloading data from eprom 2" severity:0];
	}
	result = write(filedescriptor, buf, strlen(buf));
	if (result == -1) {
		NSLog(@"writing: error %i, %s\n", errno, strerror(errno));
		return nil;
	}
	// read back the 'd ' or 'm '
	sleep(2);
	if ([self isDataAvailable]) {
		i = read(filedescriptor, &buf, 2);
	} 
	if (!(buf[0] == 'm' || buf[0] == 'd') && buf[1] != ' ')  {
		[appDelegate log:@"Error after command, invalid response (error x)" severity:2];
		return nil;
	}
	// read the data
	while ([self isDataAvailable]) {
		i = read(filedescriptor, &buf, 1024);
		total_bytes_read += i;
		[buffer appendBytes:buf length:i];
		//NSLog(@"read %i bytes (total: %i)", i, total_bytes_read);
		[appDelegate updateNumBytesRead:(double)100*(double) i/32776];
		sleep(2);
	}
	return buffer;
}


@end
